home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Utilities / Text Processing / Alpha / Tcl / SystemCode / alphaHooks.tcl < prev    next >
Encoding:
Text File  |  1997-12-20  |  18.4 KB  |  591 lines  |  [TEXT/ALFA]

  1. ## -*-Tcl-*-
  2.  # ###################################################################
  3.  #  Vince's Additions - an extension package for Alpha
  4.  # 
  5.  #  FILE: "alphaHooks.tcl"
  6.  #                                    created: 18/7/97 {5:10:18 pm} 
  7.  #                                last update: 20/12/97 {7:18:17 pm} 
  8.  #  Author: Vince Darley
  9.  #  E-mail: <darley@fas.harvard.edu>
  10.  #    mail: Division of Engineering and Applied Sciences, Harvard University
  11.  #          Oxford Street, Cambridge MA 02138, USA
  12.  #     www: <http://www.fas.harvard.edu/~darley/>
  13.  #  
  14.  # Copyright (c) 1997  Vince Darley
  15.  #  
  16.  # Description: 
  17.  #  
  18.  #  Here are the current hooks:
  19.  #  
  20.  #  activateHook changeMode closeHook deactivateHook modifyModeFlags 
  21.  #  quitHook resumeHook saveasHook saveHook savePostHook suspendHook
  22.  #  openHook
  23.  #  
  24.  #  There's also a 'mode::init' hook which will be called the first
  25.  #  time a mode is started up.  Note that the mode exists, but its
  26.  #  variables have not yet been made global, and its menus have not
  27.  #  yet been inserted into the menu bar.
  28.  #  
  29.  #  There's also a 'startupHook' which is called when Alpha starts
  30.  #  up, but after all other initialisation has taken place (before
  31.  #  any files are opened though).
  32.  #  
  33.  #  There's also a 'launch' hook for when an app is launched.
  34.  #  
  35.  #  Use of such lists as 'savePostHooks' is obsolete.
  36.  #  These lists are ignored, use hook::register instead.
  37.  #  
  38.  #  History
  39.  # 
  40.  #  modified by  rev reason
  41.  #  -------- --- --- -----------
  42.  #  18/7/97  VMD 1.0 original
  43.  #  22/7/97  VMD 1.1 fixed all bugs ;-) and added the above examples.
  44.  # ###################################################################
  45.  ##
  46.  
  47. namespace eval mode {}
  48. namespace eval win {}
  49.  
  50. proc saveHook name {
  51.     global backup backupExtension backupFolder mode win::Modes \
  52.       backupAgeRequirementInHours
  53.     hook::callAll saveHook [set win::Modes($name)] $name 
  54.     if $backup {
  55.         set dir $backupFolder
  56.             
  57.         if {![string length $dir]} {
  58.             set dir [file dirname $name]
  59.         }
  60.         if {![file exists $dir]} {
  61.             if {[dialog::yesno "Create backup dir '$dir'?"]} {
  62.                 mkdir $dir
  63.             }
  64.         }
  65.         set backfile $dir:[file tail $name]$backupExtension
  66.         if {[file exists $backfile]} {
  67.             getFileInfo $name a
  68.             if {[expr ([now] - $a(modified) + 0.0)/3600] < $backupAgeRequirementInHours} {
  69.                 return
  70.             }
  71.             catch {removeFile $backfile}
  72.         }
  73.         message "Backing up…$backfile"
  74.         catch {copyFile $name $backfile}
  75.     }
  76. }
  77.  
  78. proc saveUnmodified {} {
  79.     set name [win::Current]
  80.     if {[file exists $name] || \
  81.       ([regsub { <\w+>$} $name {} name] && [file exists $name])} {
  82.         getFileInfo $name arr
  83.         set mod $arr(modified)
  84.         save
  85.         setFileInfo $name modified $mod
  86.         return
  87.     }
  88.     # shouldn't really get here!
  89.     error "File doesn't exist"
  90. }
  91.  
  92. ## 
  93.  # -------------------------------------------------------------------------
  94.  # 
  95.  # "changeMode" --
  96.  # 
  97.  #  A very important procedure.  It handles all switching from one mode
  98.  #  to another.  This means it has to adjust menus, floating windows,
  99.  #  global variables, mode prefs, and call a number of hooks.
  100.  #  
  101.  #  It maintains a list of variables which the new mode over-rides from
  102.  #  the global scope, and recreates them.  This allows a mode to have
  103.  #  its own value for a global variable without messing anything up.
  104.  # -------------------------------------------------------------------------
  105.  ##
  106. proc changeMode {newMode} {
  107.     global lastMode modeMenus dummyProc mode seenMode PREFS globalMenus_curr
  108.     global global::_vars
  109.     
  110.     set lastMode $mode
  111.     set mode $newMode
  112.     if {$lastMode == $mode} {
  113.         catch {displayMode $newMode}
  114.         return
  115.     } elseif {$lastMode == ""} {
  116.         catch {menuEnableHook 1}
  117.     } elseif {$mode == ""} {
  118.         catch {menuEnableHook 0}
  119.     }
  120.     global ${lastMode}modeVars
  121.     if {[info exists ${lastMode}modeVars]} {
  122.         foreach v [array names ${lastMode}modeVars] {
  123.             global $v
  124.             catch {unset $v}
  125.         }
  126.     }
  127.     floatShowHide off $lastMode
  128.     if [info exists global::_vars] { 
  129.         uplevel \#0 ${global::_vars}
  130.         unset global::_vars
  131.     }
  132.     if {[info exists modeMenus($lastMode)]} {
  133.         if {[info exists modeMenus($mode)]} {
  134.             set oldMenus modeMenus($mode)
  135.         } else {
  136.             set oldMenus ""
  137.         }
  138.         foreach m $modeMenus($lastMode) {
  139.             if {([lsearch $globalMenus_curr $m] < 0) && ([lsearch $oldMenus $m] < 0)} {
  140.                 global $m
  141.                 catch {removeMenu [set $m]}
  142.             }
  143.         }
  144.     }
  145.     
  146.     # These lines must load the mode vars into the mode var scope.
  147.     if {[info exists dummyProc($mode)]} { $dummyProc($mode) }
  148.     if {![info exists seenMode($mode)]} {
  149.         hook::callAll mode::init $mode
  150.     }
  151.     # once the vars are in mode-var scope (= the <mode>modeVars array),
  152.     # they can be transfered to the global scope.  A future version of
  153.     # Alpha with Tcl8.0 namespaces may not need to do this.
  154.     global ${mode}modeVars
  155.     if {[info exists ${mode}modeVars]} {
  156.         foreach v [array names ${mode}modeVars] {
  157.             global $v
  158.             if [info exists $v] { append global::_vars "set $v \{[set $v]\} ;" }
  159.             set $v [set ${mode}modeVars($v)]
  160.         }
  161.     }
  162.     if {[info exists modeMenus($mode)]} {
  163.         foreach m $modeMenus($mode) {
  164.             catch {$m}
  165.             global $m
  166.             catch {insertMenu [set $m]}
  167.         }
  168.     }
  169.     
  170.     floatShowHide on $mode
  171.  
  172.     if {![info exists seenMode($mode)]} {
  173.         set seenMode($mode) 1
  174.         if {($mode != "") && [file exists "$PREFS:${mode}Prefs.tcl"]} {
  175.             if {[catch {uplevel \#0 [list source "$PREFS:${mode}Prefs.tcl"]}]} {
  176.                 alertnote "Your preferences file '${mode}Prefs.tcl has an error."
  177.             } 
  178.         }
  179.     }
  180.         
  181.     catch {displayMode $newMode}
  182.  
  183.     hook::callAll changeMode $mode $mode
  184. }
  185. ## 
  186.  # -------------------------------------------------------------------------
  187.  # 
  188.  # "requireOpenWindowsHook" --
  189.  # 
  190.  #  En-/disable meaningless menu items which would require the presence
  191.  #  of a certain number of windows to be active
  192.  #  
  193.  #  This proc should only be called from 'openHook' and 'closeHook'.
  194.  #  
  195.  #  You can register with it using 
  196.  #  
  197.  #  'hook::register requireOpenWindowsHook [list menu item] N'
  198.  #  
  199.  #  where 'N' is the number of windows required (1 or 2 usually)
  200.  #  (and deregister etc using hook::deregister).
  201.  #  
  202.  #  We only really need the catch in here for two reasons:
  203.  #  (i) in case bad menus are registered accidentally
  204.  #  (ii) so startup errors can open a window without hitting another error
  205.  #  in the middle of doing that!
  206.  # -------------------------------------------------------------------------
  207.  ##
  208. proc requireOpenWindowsHook {requiredNum} {
  209.     foreach count $requiredNum {
  210.         set enable [expr [llength [winNames]] >= $requiredNum ? 1 : 0]
  211.         foreach i [hook::list requireOpenWindowsHook $requiredNum] {
  212.             catch "enableMenuItem $i $enable"
  213.         }
  214.     }
  215. }
  216.  
  217. ## 
  218.  # -------------------------------------------------------------------------
  219.  # 
  220.  # "menuEnableHook" --
  221.  # 
  222.  #  This hook is called to turn menu items on or off.  It is called 
  223.  #  whenever there are no windows, or when we go from 0->1 window.
  224.  #  
  225.  #  It should deal with all standard menus.  It does not deal with
  226.  #  special menu items like 'save', 'revert',.. which require more
  227.  #  information.
  228.  #  
  229.  #  It is called from changeMode.
  230.  #  
  231.  #  Andreas wrote most of this proc.
  232.  #  
  233.  #  Due to a deficiency in MacOS/MercutioMDEF/Alpha (not sure who
  234.  #  the culprit is!), key-bindings attached to menu items are still
  235.  #  triggered even if the menu item is inactive.
  236.  # -------------------------------------------------------------------------
  237.  ##
  238. proc menuEnableHook {{haveWin 1}} {
  239.     global winMenu
  240.     # we only get here if there are no windows, or 1 window which we
  241.     # just opened.  Otherwise nothing will be different to last time.
  242.     enableMenuItem Config currentMode $haveWin
  243.     enableMenuItem File close $haveWin
  244.     enableMenuItem File closeAll $haveWin
  245.     enableMenuItem File closeFloat $haveWin
  246.     enableMenuItem File saveAs… $haveWin
  247.     enableMenuItem File saveACopyAs… $haveWin
  248.     if {[package::active printerChoicesMenu]} {
  249.         enableMenuItem File print $haveWin
  250.     } else {
  251.         enableMenuItem File print… $haveWin
  252.     }
  253.     eval [lindex [list un {}] $haveWin]bind 'p' <c> print
  254.  
  255.     enableMenuItem Edit undo $haveWin
  256.     enableMenuItem Edit redo $haveWin
  257.     enableMenuItem Edit load $haveWin
  258.     enableMenuItem Edit cut&Append $haveWin
  259.     enableMenuItem Edit copy&Append $haveWin
  260.     enableMenuItem Edit pastePop $haveWin
  261.     enableMenuItem Edit selectParagraph $haveWin
  262.     enableMenuItem Edit twiddle $haveWin
  263.     enableMenuItem Edit twiddleWords $haveWin
  264.     enableMenuItem Edit shiftLeft  $haveWin
  265.     enableMenuItem Edit shiftLeftSpace  $haveWin
  266.     enableMenuItem Edit shiftRight  $haveWin
  267.     enableMenuItem Edit shiftRightSpace  $haveWin
  268.     enableMenuItem Edit balance  $haveWin
  269.     enableMenuItem Edit emacs $haveWin
  270.  
  271.     enableMenuItem Text fillParagraph $haveWin
  272.     enableMenuItem Text wrapParagraph $haveWin
  273.     enableMenuItem Text sentenceParagraph $haveWin
  274.     enableMenuItem Text fillRegion $haveWin
  275.     enableMenuItem Text wrapRegion $haveWin
  276.     enableMenuItem Text sentenceRegion $haveWin
  277.     enableMenuItem Text paragraphToLine $haveWin
  278.     enableMenuItem Text lineToParagraph $haveWin
  279.     enableMenuItem Text reverseSort $haveWin
  280.     enableMenuItem Text sortLines $haveWin
  281.     enableMenuItem Text spellcheckWindow $haveWin
  282.     enableMenuItem Text spellcheckSelection $haveWin
  283.     enableMenuItem Text zapInvisibles $haveWin
  284.     enableMenuItem Text tabsToSpaces $haveWin
  285.     enableMenuItem Text spacesToTabs $haveWin
  286.     enableMenuItem Text indentLine $haveWin
  287.     enableMenuItem Text indentRegion $haveWin
  288.     enableMenuItem Text upcaseRegion $haveWin
  289.     enableMenuItem Text downcaseRegion $haveWin
  290.     enableMenuItem Text strings $haveWin
  291.     enableMenuItem Text commentLine $haveWin
  292.     enableMenuItem Text uncommentLine $haveWin
  293.     enableMenuItem Text commentBox $haveWin
  294.     enableMenuItem Text uncommentBox $haveWin
  295.     enableMenuItem Text commentParagraph $haveWin
  296.     enableMenuItem Text uncommentParagraph $haveWin
  297.     enableMenuItem Text gotoFunc $haveWin
  298.     # These four don't work because of a bug in Alpha.
  299.     # It won't recognise items near the end of long menus
  300.     # (long is > 20 items or so).  We leave them in hoping
  301.     # for the future...
  302.      enableMenuItem Text gotoFileMark $haveWin
  303.      enableMenuItem Text markHilite $haveWin
  304.      enableMenuItem Text namedMarks $haveWin
  305.     enableMenuItem Text unnamedMarks $haveWin
  306.     # Temporary work-around: disable all submenu items
  307.     enableMenuItem namedMarks set… $haveWin
  308.     enableMenuItem namedMarks goto… $haveWin
  309.     enableMenuItem namedMarks remove… $haveWin
  310.     enableMenuItem namedMarks sort $haveWin
  311.     enableMenuItem namedMarks sortByPosition $haveWin
  312.     enableMenuItem unnamedMarks set… $haveWin
  313.     enableMenuItem unnamedMarks exchangePointAndMark $haveWin
  314.  
  315.     enableMenuItem Search searchStart $haveWin
  316.     enableMenuItem Search findAgain $haveWin
  317.     enableMenuItem Search findAgainBackward $haveWin
  318.     enableMenuItem Search enterSearchString $haveWin
  319.     enableMenuItem Search enterReplaceString $haveWin
  320.     enableMenuItem Search quickFind $haveWin
  321.     enableMenuItem Search quickFindRegexp $haveWin
  322.     enableMenuItem Search reverseQuickFind $haveWin
  323.     enableMenuItem Search replace $haveWin
  324.     enableMenuItem Search replace&FindAgain $haveWin
  325.     enableMenuItem Search replaceAll $haveWin
  326.     enableMenuItem Search pushPosition $haveWin
  327.     enableMenuItem Search popPosition $haveWin
  328.     enableMenuItem Search gotoLine $haveWin
  329.  
  330.     enableMenuItem Utils AsciiEtc $haveWin
  331.     enableMenuItem Utils matchingLines $haveWin
  332.     enableMenuItem Utils gotoMatch $haveWin
  333.     enableMenuItem Utils nextMatch $haveWin
  334.     enableMenuItem Utils cmdDoubleClick $haveWin
  335.     enableMenuItem Utils winUtils $haveWin
  336.  
  337.     enableMenuItem Config setFontsTabs… $haveWin
  338.     enableMenuItem Config currentMode $haveWin
  339.  
  340.     enableMenuItem $winMenu zoom $haveWin
  341.     enableMenuItem $winMenu singlePage $haveWin
  342.     enableMenuItem $winMenu chooseAWindow $haveWin
  343.     enableMenuItem $winMenu iconify $haveWin
  344.     enableMenuItem $winMenu arrange $haveWin
  345.     enableMenuItem $winMenu splitWindow $haveWin
  346.     enableMenuItem $winMenu toggleScrollbar $haveWin
  347.     
  348.     if {!$haveWin} {
  349.         enableMenuItem File save 0
  350.         enableMenuItem File saveUnmodified 0
  351.         enableMenuItem File revert 0
  352.         enableMenuItem File revertToBackup 0
  353.         enableMenuItem File renameTo… 0
  354.         enableMenuItem File saveAll 0
  355.     }
  356.  
  357.     requireOpenWindowsHook 1
  358. }
  359.  
  360. proc savePostHook name {
  361.     hook::callAll savePostHook "" $name
  362. }
  363.  
  364. proc closeHook name {
  365.     global markStack win::Modes win::Active win::Current win::Dirty win::NumDirty
  366.     hook::callAll closeHook [set win::Modes($name)] $name
  367.  
  368.     if {[info exists win::Dirty($name)]} {
  369.         incr win::NumDirty -1
  370.         unset win::Dirty($name)
  371.         enableMenuItem File saveAll [expr ${win::NumDirty} ? 1 : 0]
  372.     }
  373.         
  374.     unset win::Modes($name)
  375.     if [llength $markStack] {
  376.         set markStack [lremove -glob $markStack $name*]
  377.     }
  378.     win::removeFromMenu $name
  379.  
  380.     if {[set ind [lsearch ${win::Active} $name]] >= 0} {
  381.         set win::Active [lreplace ${win::Active} $ind $ind]
  382.     }
  383.     if {![llength [winNames]]} {
  384.         set win::Current ""
  385.         changeMode {}
  386.     }
  387.     requireOpenWindowsHook 2
  388. }
  389.  
  390. proc deactivateHook name {
  391.     hook::callAll deactivateHook "" $name
  392. }
  393.  
  394. proc suspendHook name {
  395.     hook::callAll suspendHook "" $name
  396.     global iconifyOnSwitch
  397.     global suspIconed
  398.     if {$iconifyOnSwitch} {
  399.         set wins [winNames -f]
  400.         set suspIconed ""
  401.         foreach win $wins {
  402.             if {![icon -f "$win" -q]} {
  403.                 lappend suspIconed $win
  404.                 icon -f "$win" -t
  405.             }
  406.         }
  407.         set suspIconed [lreverse $suspIconed]
  408.     }
  409. }
  410.  
  411. ensureset killCompilerErrors 0
  412. proc resumeHook name {
  413.     global iconifyOnSwitch resumeRevert suspIconed killCompilerErrors
  414.  
  415.     if {$killCompilerErrors} {
  416.         set wins [winNames -f]
  417.         if {[set res [lsearch $wins "*Compiler Errors*"]] >= 0} {
  418.             bringToFront [lindex $wins $res]
  419.             killWindow
  420.         }
  421.     }
  422.     
  423.     if {$iconifyOnSwitch && [info exists suspIconed]} {
  424.         set wins [winNames -f]
  425.         foreach win $suspIconed {
  426.             icon -f "$win" -o
  427.         }
  428.         unset suspIconed
  429.     }
  430.     if {$resumeRevert} {
  431.         set resumeRevert 0
  432.         revert
  433.     }
  434.     hook::callAll resumeHook "" $name
  435. }
  436.  
  437. # Added 'refresh'
  438. # Added oldName as an argument to hook::callAll
  439. # All saveasHooks should take these two arguments.
  440. # I needed both args in a hook I just made...
  441. proc saveasHook {oldName newName} {
  442.     global win::Modes win::Active
  443.     if {$oldName == $newName} return
  444.     win::removeFromMenu $oldName
  445.     win::addToMenu $newName
  446.     win::setMode $newName
  447.     changeMode [set win::Modes($newName)]
  448.     
  449.     hook::callAll saveasHook [set win::Modes($newName)] $oldName $newName
  450.  
  451.     if {[set ind [lsearch ${win::Active} $oldName]] >= 0} {
  452.         set win::Active [lreplace ${win::Active} $ind $ind]
  453.     }
  454.     set win::Active [linsert ${win::Active} 0 $newName]
  455.     catch {unset win::Modes($oldName)}
  456.     refresh
  457. }
  458. ensureset win::Active ""
  459.  
  460. proc activateHook {name} {
  461.     global win::Modes win::Active win::Current
  462.  
  463.     if {![info exists win::Modes($name)]} {
  464.         win::setMode $name
  465.     }
  466.     if {[set ind [lsearch -exact ${win::Active} $name]] == -1} {
  467.         set win::Active [linsert ${win::Active} 0 $name]
  468.     } elseif {$ind >= 1} {
  469.         set win::Active [lreplace ${win::Active} $ind $ind]
  470.         set win::Active [linsert ${win::Active} 0 $name]
  471.     }
  472.     set win::Current $name
  473.     
  474.     changeMode [set win::Modes($name)]
  475.     
  476.     hook::callAll activateHook [set win::Modes($name)] $name
  477.  
  478.     # if the file exists (this seems to be the quickest way to check)
  479.     if {[file exists $name] || \
  480.       ([regsub { <\w+>$} $name {} nm] && [file exists $nm])} {
  481.         # this fails if the window is just opening, but then we know it's clean
  482.         if [catch {getWinInfo -w $name arr}] {
  483.             set dirty 0
  484.         } else {
  485.             set dirty $arr(dirty)
  486.         }
  487.         enableMenuItem File save $dirty
  488.         enableMenuItem File saveUnmodified $dirty
  489.         enableMenuItem File revert $dirty
  490.         enableMenuItem File revertToBackup 1
  491.         enableMenuItem File renameTo… 1
  492.     } else {
  493.         enableMenuItem File save 0
  494.         enableMenuItem File saveUnmodified 0
  495.         enableMenuItem File revert 0
  496.         enableMenuItem File revertToBackup 0
  497.         enableMenuItem File renameTo… 0
  498.     }
  499.     
  500. }
  501.  
  502. proc quitHook {} {
  503.     global PREFS
  504.     if {[file exists "$PREFS:ftpTmp"]} {
  505.         catch {rm "$PREFS:ftpTmp:*"}
  506.     }
  507.     saveModifiedVars
  508.     hook::callAll quitHook
  509. }
  510.  
  511. ## 
  512.  # -------------------------------------------------------------------------
  513.  # 
  514.  # "dirtyHook" --
  515.  # 
  516.  #  This proc currently has to keep track in the array 'win::Dirty' of
  517.  #  the dirty status of windows.  Its only use is if we close a dirty
  518.  #  window and select 'discard', we would otherwise have a faulty
  519.  #  'win::NumDirty' count.  If there's a different solution we should
  520.  #  get rid of the win::Dirty array.
  521.  #  
  522.  #  Note: closeHook is called after the window is gone, and killWindow
  523.  #  isn't called if you click in the close-box, so they don't solve
  524.  #  the problem.
  525.  # -------------------------------------------------------------------------
  526.  ##
  527. proc dirtyHook {name dirty} {
  528.     global winMenu win::NumDirty win::Dirty
  529.     markMenuItem $winMenu [file tail $name] $dirty "◊"
  530.     if {$dirty == "on"} {
  531.         set win::Dirty($name) 1
  532.         incr win::NumDirty 1
  533.     } else {
  534.         catch {unset win::Dirty($name)}
  535.         incr win::NumDirty -1
  536.     }
  537.     enableMenuItem File save $dirty
  538.     enableMenuItem File saveUnmodified $dirty
  539.     enableMenuItem File revert $dirty
  540.     enableMenuItem File saveAll [expr ${win::NumDirty} ? 1 : 0]
  541.     # we may still revertToBackup even if the file is clean.
  542.     # however we can't just revert.
  543. }
  544.  
  545. proc openHook name {
  546.     global win::Modes autoMark mode screenHeight screenWidth \
  547.       forceMainScreen
  548.  
  549.     changeMode [set win::Modes($name)]
  550.     regsub -all {\\([][])} $name {\1} nm
  551.     win::addToMenu $nm
  552.     message ""
  553.  
  554.     if {![catch {getFileInfo $name info}]} {
  555.         if {$info(creator) == {ttxt}} {
  556.             setWinInfo dirty 0
  557.         }
  558.         if {$info(type) == {ttro}} {
  559.             catch {setWinInfo read-only 1}
  560.             message "Read-only!"
  561.         }
  562.     }
  563.  
  564.     global ${mode}modeVars
  565.     
  566.     if {$forceMainScreen} {
  567.         set geo [getGeometry]
  568.         set l [lindex $geo 0]; set t [lindex $geo 1]; set w [lindex $geo 2]; set h [lindex $geo 3]; 
  569.         if {($l < 0) || ($t < 35) || ([expr $l + $w] > $screenWidth) || ([expr $t + $h + 18] > $screenHeight)} {
  570.             singlePage
  571.         }
  572.     }
  573.     getWinInfo arr
  574.     if !$arr(read-only) {
  575.         if {[info exists ${mode}modeVars(autoMark)] \
  576.             && [set ${mode}modeVars(autoMark)] \
  577.             && ![llength [getNamedMarks -n]]} {
  578.             markFile
  579.         }
  580.     }
  581.  
  582.     global PREFS
  583.     if {[string match "${PREFS}*defs.tcl" $name]} {setWinInfo read-only 1}
  584.     
  585.     requireOpenWindowsHook 2
  586.     
  587.     hook::callAll openHook [set win::Modes($name)] $name
  588. }
  589.  
  590.  
  591.